/*
 * Copyright (C) 2006 Johan Maasing johan at zoom.nu Licensed under the Apache
 * License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
 * or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package nu.zoom.catonine.swing.rule;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;

import nu.zoom.catonine.fontchooser.FontChooser;
import nu.zoom.catonine.fontchooser.FontChooserFactory;
import nu.zoom.catonine.stylerule.StyleRule;
import nu.zoom.gal.error.ErrorReporter;
import nu.zoom.swing.action.AbstractTypedAction;
import nu.zoom.swing.desktop.Workbench;
import nu.zoom.swing.field.PatternField;
import nu.zoom.swing.layout.VerticalPanel;
import nu.zoom.ui.Resources;
import nu.zoom.ui.Resources.ResourceNotFoundException;

/**
 * A panel that allows editing of the styling rules in a collection of style
 * rules. Adding/removing style rules and defining the regular expression and
 * color of the log entries.
 * 
 * @author "Johan Maasing" &lt;johan@zoom.nu&gt;
 * 
 */
public class StyleRuleEditPanel extends JPanel {

	private static final long serialVersionUID = 1L;
	private final FontChooserFactory fontChooserFactory;
	private final Workbench workbench;
	private final ErrorReporter errorReporter;
	private final Resources messages;
	private JCheckBox supressCheckBox;
	private JButton foregroundColorChooser;
	private JButton backgroundColorChooser;
	private JButton fontSelectButton;
	private StyleRulePatternField patternTextField;
	private StyleRule styleRule;
	public final Font defaultFont;

	public StyleRuleEditPanel(final Workbench workbench,
			final FontChooserFactory fontChooserFactory,
			final Resources messages, final ErrorReporter errorReporter,
			final Font defaultFont) throws ResourceNotFoundException {
		super(new BorderLayout());
		this.fontChooserFactory = fontChooserFactory;
		this.workbench = workbench;
		this.errorReporter = errorReporter;
		this.messages = messages;
		this.defaultFont = defaultFont;

		final ForegroundAction foregroundAction = new ForegroundAction(messages);
		final BackgroundAction backgroundAction = new BackgroundAction(messages);
		this.foregroundColorChooser = new JButton(foregroundAction);
		this.backgroundColorChooser = new JButton(backgroundAction);
		this.fontSelectButton = new JButton(new FontChooserAction());
		final JLabel patternLabel = new JLabel(
				messages.getMessage("nu.zoom.catonine.stylerule.pattern"));
		patternTextField = new StyleRulePatternField(patternLabel);
		patternTextField.setToolTipText(messages
				.getMessage("nu.zoom.catonine.stylerule.pattern.tt"));
		supressCheckBox = new JCheckBox(new SupressAction());

		final JPanel dialogButtonPanel = new JPanel(new FlowLayout());
		dialogButtonPanel.add(foregroundColorChooser);
		dialogButtonPanel.add(backgroundColorChooser);
		dialogButtonPanel.add(fontSelectButton);

		final VerticalPanel mainPanel = new VerticalPanel();
		mainPanel.addRow(patternLabel, patternTextField);
		mainPanel.addRow(
				messages.getMessage("nu.zoom.catonine.stylerule.supress"),
				supressCheckBox);
		mainPanel.addRow(dialogButtonPanel);
		add(mainPanel, BorderLayout.CENTER);
	}

	class ForegroundAction extends AbstractTypedAction {

		private static final long serialVersionUID = 1L;
		private final String chooserTooltip;

		public ForegroundAction(Resources messages)
				throws ResourceNotFoundException {
			super();
			setName(messages
					.getMessage("nu.zoom.catonine.stylerule.foreground"));
			setToolTip(messages
					.getMessage("nu.zoom.catonine.stylerule.foreground.tt"));
			setIcon(messages
					.getIcon("nu.zoom.catonine.stylerule.foreground.icon"));
			this.chooserTooltip = messages
					.getMessage("nu.zoom.catonine.stylerule.foreground.tt");
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			Color selectedColor = JColorChooser.showDialog(
					StyleRuleEditPanel.this, chooserTooltip,
					(styleRule != null) ? styleRule.getForeground()
							: Color.BLACK);
			if ((selectedColor != null) && (styleRule != null)) {
				styleRule.setForeground(selectedColor);
			}
		}
	}

	class BackgroundAction extends AbstractTypedAction {

		private static final long serialVersionUID = 1L;
		private final String chooserTooltip;

		public BackgroundAction(Resources messages)
				throws ResourceNotFoundException {
			super();
			setName(messages
					.getMessage("nu.zoom.catonine.stylerule.background"));
			setToolTip(messages
					.getMessage("nu.zoom.catonine.stylerule.background.tt"));
			setIcon(messages
					.getIcon("nu.zoom.catonine.stylerule.background.icon"));
			this.chooserTooltip = messages
					.getMessage("nu.zoom.catonine.stylerule.foreground.tt");
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			Color selectedColor = JColorChooser.showDialog(
					StyleRuleEditPanel.this, chooserTooltip,
					(styleRule != null) ? styleRule.getBackground()
							: Color.WHITE);
			if ((selectedColor != null) && (styleRule != null)) {
				styleRule.setBackground(selectedColor);
			}
		}
	}

	class SupressAction extends AbstractAction {

		private static final long serialVersionUID = 1L;

		@Override
		public void actionPerformed(ActionEvent e) {
			boolean supress = supressCheckBox.isSelected();
			foregroundColorChooser.setEnabled(!supress);
			backgroundColorChooser.setEnabled(!supress);
			patternTextField.setEnabled(!supress);
			if (styleRule != null) {
				styleRule.setSupress(supress);
			}
		}
	}

	class FontChooserAction extends AbstractTypedAction {
		private static final long serialVersionUID = -1795111337760951406L;

		public FontChooserAction() throws ResourceNotFoundException {
			super();
			setName(messages
					.getMessage("nu.zoom.catonine.fontchooser.activate"));
			setIcon(messages
					.getIcon("nu.zoom.catonine.fontchooser.activate.icon"));
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			try {
				final FontChooser fontChooser = fontChooserFactory
						.getFontChooser();
				fontChooser
						.addFontValuesListener(new FontChooser.FontValuesListener() {

							@Override
							public void fontValuesChanged(
									final FontChooser source, final Font font) {
								if (styleRule != null) {
									styleRule.setFont(font);
								}
							}
						});
				Font startFont = null;
				if (styleRule != null) {
					startFont = styleRule.getFont();
				}
				final JComponent fontChooserGUI = fontChooser
						.getFontChooserGUI(startFont, defaultFont);
				final JDialog dlg = new JDialog(workbench.getDialogOwner());
				// Neither of these positions work good.
				dlg.setLocationRelativeTo(workbench.getDialogOwner());
				// dlg.setLocationRelativeTo(StyleRuleEditPanel.this);
				JButton closeButton = new JButton(
						messages.getMessage("nu.zoom.catonine.fontchooser.dispose"));
				closeButton.addActionListener(new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent e) {
						dlg.dispose();
					}
				});
				JPanel buttonPanel = new JPanel(new FlowLayout(
						FlowLayout.CENTER));
				buttonPanel.add(closeButton);
				dlg.add(fontChooserGUI, BorderLayout.CENTER);
				dlg.add(buttonPanel, BorderLayout.SOUTH);
				dlg.setVisible(true);
				dlg.pack();
			} catch (ResourceNotFoundException e1) {
				errorReporter.reportError(e1);
			}
		}
	}

	/**
	 * @param styleRule
	 *            The styleRule to set.
	 */
	public void setStyleRule(StyleRule styleRule) {
		if (styleRule == null) {
			unsetStyleRule();
		} else {
			this.styleRule = styleRule;
			final boolean supress = styleRule.isSupress();
			this.foregroundColorChooser.setEnabled(!supress);
			this.backgroundColorChooser.setEnabled(!supress);
			this.patternTextField.setEnabled(!supress);
			this.supressCheckBox.setEnabled(true);
			this.supressCheckBox.setSelected(supress);
			this.patternTextField.setText(styleRule.getPattern().toString());
			this.fontSelectButton.setEnabled(true);
		}
	}

	void unsetStyleRule() {
		this.styleRule = null;
		this.patternTextField.setText("");
		this.foregroundColorChooser.setEnabled(false);
		this.backgroundColorChooser.setEnabled(false);
		this.patternTextField.setEnabled(false);
		this.supressCheckBox.setEnabled(false);
		this.supressCheckBox.setSelected(false);
		this.fontSelectButton.setEnabled(false);
	}

	class StyleRulePatternField extends PatternField {

		private static final long serialVersionUID = 1L;

		public StyleRulePatternField(JLabel label) {
			super(label);
		}

		@Override
		protected void validationPassed() {
			super.validationPassed();
			// Is there a selected style rule? Document might change even if
			// there is no active style rule (for example from "unset".
			if (styleRule != null) {
				styleRule.setPattern(getText());
			}
		}
	}
}
